package cn.johnyu.controller;

import cn.johnyu.domain.Account;
import cn.johnyu.service.AuthenPersistenceService;
import cn.johnyu.util.GsonUtil;
import cn.johnyu.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

@Slf4j
@RestController
public class AuthenticationController {
    @Autowired
    private ReactiveAuthenticationManager authenticationManager;
    @Autowired
    private AuthenPersistenceService authenPersistenceService;

    /**
     * 根据用户名和密码生成"认证令牌"，并使用“认证管理器”进行认证，如果认证成功，生成jwt token，并进行持久化
     */
    @PostMapping("/login")
    public Mono<String> login(@RequestParam("username") String username, @RequestParam("password") String password) {
        var authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
        //进行认证
        Mono<Authentication> authenticationMono = authenticationManager
                .authenticate(authenticationToken)
                .onErrorResume(e -> Mono.empty());
        //如果认证成功，生成jwt token，并进行持久化
        return authenticationMono.flatMap(auth -> {
            Account account =(Account) auth.getPrincipal(); //返回的类型取决于UserDetailsService的实现类
            log.info("account:{}",account);
            log.info("username:{},authorities:{}", auth.getName(), auth.getAuthorities());
//            List<String> roles = auth.getAuthorities().stream().map(a -> a.getAuthority()).toList();
//            Account account = new Account(null, auth.getName(), null, roles);

            String jwtToken = JwtUtil.generateToken(GsonUtil.accountToJson(account));
            //  对令牌进行持久化
            return authenPersistenceService.save(jwtToken)
                    .map(rs -> rs ? jwtToken : "持久化令牌时失败！");
        })//如果认证失败，返回错误信息
                .defaultIfEmpty("用户名或密码错误！");
    }

    @PostMapping("/logout")
    public Mono<String> logout(ServerWebExchange exchange) {
        String token = exchange.getRequest().getHeaders().getFirst("Token");
        log.info("token:{}", token);
        return authenPersistenceService.delete(token).flatMap(delete -> Mono.just("logout success"));
    }
}
